/**
 * @brief GPS控制模块
 * @version 1.0
 * @date
 * @author 宋炜
*/

#ifndef __GPS_CTRL__
#define __GPS_CTRL__
#include <string>
#include <functional>

#include <ql_oe.h>

#include "misc.h"

class gpsCtrl
{
public:
	static gpsCtrl * gpsDevice;
private:
	/**
	* @brief void cb_on_navigate( bool start_or_stop )
	* @param true , 启动； false 停止
	*/
	std::function< void ( bool ) >   								cb_on_navigate;
	/**
	 * @brief void cb_on_data( double latitude , double longitude , double altitude , double accuracy)
	 * @param latitude , 纬度
	 * @param longitude , 经度
	 * @param altitude , 高度
	 * @param accuracy , 精度
	*/
	std::function< void ( double , double , double , double ) >   	cb_on_data;
	/**
	 * @brief 电源情况变化回调函数; void on_cb_power( bool sw )
	 * @param sw , true 开启； false 关闭
	*/
	std::function< void ( bool ) > 									cb_on_power;
	/**
	 * @brief 卫星变化。void cb_on_satllites( int count );
	 * @param count , 当前可见卫星数量
	*/
	std::function< void ( int ) > 									cb_on_satllites;
	/**
	 * @brief 移动参数回调函数; void cb_on_speed( float head_degree , float speed );
	 * @param head_degree , 方向角度
	 * @param speed , 移动速度，单位为 m/s
	*/
	std::function< void ( float , float )>                          cb_on_speed;
	/**
	 * @brief 当前可见卫星发生变化
	*/
	std::function< void( int ) > cb_on_sv;
private:
	bool                    		m_is_running;   // 是否正在执行定位

	loc_client_handle_type   		h_loc;			// GPS ID
	int                     		bitmask;
    	QL_LOC_POS_MODE_INFO_T  		t_mode;
    	QL_LOC_LOCATION_INFO_T  		t_loc_info;
	QL_LOC_SV_STATUS_T      		t_sv_info;		// 卫星信息
	QL_LOC_AGPS_STATUS_T            m_agps_status;  // AGPS 状态
private:
	/**
	* @brief 初始化定位操作掩码。从配置文件读取功能配置，然后生成掩码
	*/
	void init_bitmask();
	/**
	 * @brief 初始化定位模式
	*/
	void init_position_mode();
public:
	gpsCtrl();
	virtual ~gpsCtrl();
	/**
	 * @brief GPS操作事件绑定器
	 * @param __Callable ， 函数类型模板
	 * @param __Args ， 函数可变参数模板
	 * @param fun , 函数对象
	 * @param args , 函数对象的参数。
	*/
	template< typename __Callable , typename... __Args >
	gpsCtrl& on( const std::string& evt , __Callable&& fun ,  __Args&&... args )
	{
		switch ( hash_( evt.c_str() )) {
			case hash_compile_time("satellites"):  // 当前卫星状态
				cb_on_satllites( fun , args ... );
			break;
			case hash_compile_time("data"):        // 定位数据
				cb_on_data( fun , args... );
			break;
			case hash_compile_time("power"):       // 电源操作事件
				cb_on_power = std::bind( fun , args... );
			break;
			case hash_compile_time( "nav" ):       // 开始导航回调函数
				cb_on_navigate = std::bind( fun , args... );
			break;
			case hash_compile_time( "move" ):
				cb_on_speed = std::bind( fun , args... );
			break;
			default:break;
		}

		return *this;
	}

	/**
	 * @brief 启动或者停止定位
	 * @param sw , true 启动; false 停止
	 * @param fun , 状态变化后的回调函数
	*/
	void Start( bool sw );
	void Start( bool sw , std::function< void ( bool )> fun );
	/**
	 *
	*/
	void ProcessStatus( E_QL_LOC_STATUS_VALUE_T* status );
	/**
	*/
	void ProcessLocationInfo( QL_LOC_LOCATION_INFO_T* data );
	void ProcessSVInfo( QL_LOC_SV_STATUS_T *data );

	void ProcessNMEAInfo( QL_LOC_NMEA_INFO_T  * data );
	void ProcessCapabilities( E_QL_LOC_CAPABILITIES_T* data );
	void ProcessAGPSStatus( QL_LOC_AGPS_STATUS_T* data );
	void ProcessNotifaction( QL_LOC_NI_NOTIFICATION_INTO_T * data );
	void ProcessXTRAReport( QL_LOC_XTRA_REPORT_SERVER_INTO_T* data );
	/**
	*/
	int SvCount();
	/**
	 * @brief 获取当前定位信息
	*/
	void Location( double & latitude , double& longitude , double& altitude , double & accuracy );
	/**
	 * @brief 获取速度信息
	*/
	void Speed( float & speed , float & heading );
};
/**
 * @brief 初始化GPS设备
 * @return 返回对象指针，如果创建失败返回nullptr.
 * @note 这个函数返回指针并不意味着GPS可以正常工作了，有可能GPS实际处于关闭状态。
 * 所以实际的情况需要另外处理
*/
extern gpsCtrl * CreateGPS();
#endif
